package com.whately.core.base.jwt.util;


import cn.hutool.core.date.DateUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.whately.core.base.constant.LoginUser;
import com.whately.core.base.exception.ServiceException;
import com.whately.core.base.utils.AESUtils;
import com.whately.core.base.utils.GsonUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;

@Data
@Component
@Slf4j
public class JWTUtil {
    private final static String PAY_LOAD_PRIVATE = "user";

    private final static String pre_encode_work="hitoo";
    // 过期时间8小时
    private static int DEFAULT_EXPIRE_TIME_8h =  60*60*8 ; //60*60*24*7;  //过期时间，秒，一周;
    //16位aesKey
    private static final String aes_key = "b93a6ml6a76ef8f2";

    //    密钥
    private static String SECRET = "8f9575ac3d514f9b843280147b510713";

    @Value("${jwt.secret:8f9575ac3d514f9b843280147b510713}")
    public void setSECRET(String secret) {
        JWTUtil.SECRET = secret;
    }


    private static boolean JwtEncodeIdFlag = false;

    @Value("${jwt.encodeIdFlag:false}")
    public void setJwtEncodeIdFlag(boolean jwtEncodeIdFlag) {
        JWTUtil.JwtEncodeIdFlag = jwtEncodeIdFlag;
    }

    //不需要new
    private JWTUtil(){

    }

    /**
     * 生成gwt签名token
     *
     * @return 加密的token
     */
    public static String geneJsonWebToken(LoginUser loginUser) {
        return geneJsonWebToken(loginUser,DEFAULT_EXPIRE_TIME_8h);

    }

    public static String geneJsonWebToken(LoginUser loginUser,int expireTimeInSeconds) {
        if(loginUser==null||StringUtils.isBlank(loginUser.getUserId())){
            throw new ServiceException(400,"jwt user info null error");
        }

        if(JwtEncodeIdFlag){
            loginUser.setEncodeId(AESUtils.encrypt(aes_key,pre_encode_work+loginUser.getUserId()));
            loginUser.setUserId(null);
        }


        /**
         * 过期时间
         */
        Date now=new Date();
        Date expDate = DateUtil.offsetSecond(now, expireTimeInSeconds);

        Algorithm algorithm = Algorithm.HMAC256(SECRET);
        return JWT.create()
                .withClaim(PAY_LOAD_PRIVATE, GsonUtils.toJsonString(loginUser))
                .withIssuedAt(now)
                .withExpiresAt(expDate)
                .sign(algorithm);

    }


    /**
     * 校验token是否正确
     * @param token 密钥
     * @return 是否正确
     */
    public static LoginUser fetchJwtUserFromToken(String token) {
        if(StringUtils.isBlank(token)){
            return null;
        }

        try {
            String userJson = analysisToken(token);
            if(StringUtils.isBlank(userJson)){
                return null;
            }

            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withClaim(PAY_LOAD_PRIVATE, userJson)
                    .build();
            verifier.verify(token);


            LoginUser loginUser = changeUser(userJson);
            return loginUser;
        } catch (Exception exception) {
            log.error("checkJwtToken error ",exception);
            return null;
        }
    }

    private static String  analysisToken(String token){
        try{
            DecodedJWT jwt = JWT.decode(token);
            String payLoadPrivate= jwt.getClaim(PAY_LOAD_PRIVATE).asString();
            return payLoadPrivate;
        }catch (Exception e){
            log.error("analysisToken error ",e);
            return null;
        }
    }

    private static LoginUser changeUser(String user) {
        LoginUser loginUser = GsonUtils.jsonToBean(user, LoginUser.class);

        if(JwtEncodeIdFlag){
            //解密decodeId
            String decodeStr=AESUtils.decrypt(aes_key,loginUser.getEncodeId());
            if(!decodeStr.startsWith(pre_encode_work)){
                throw new RuntimeException("jwt  get user check fail ,encode starter error");
            }else{
                //去掉开头的 hitoo
                loginUser.setUserId(decodeStr.substring(pre_encode_work.length()));
            }
        }

        //最后再检查一下userId
        if(StringUtils.isBlank(loginUser.getUserId())){
            throw new RuntimeException("jwt  get user check fail ,user id null");
        }

        return loginUser;
    }



}
